﻿using UnityEngine;
using UnityEditor;
using System;
using HDJ.Framework.Core;

public class SM_InputEventController<S, T> where S : StateDataBase, new() where T : StateTransitionDataBase, new()
{
    private SM_EditorController<S, T> win;
    public SM_InputEventController(SM_EditorController<S, T> win)
    {
        this.win = win;
    }
    public Vector2 MousePosition;
    public void PlayerControlUse()
    {
        if (win == null || win.machineData == null)
            return;

        MouseBGEmptyRightClikEvent();
        OnEndNewTransitionEvent();
        OnMachineStateMouseRightClickMenu();

        KeyboardDeleteItem();
        MouseSelectObject();

        OnDragStateGUI();

        OnCopyState();
        OnPauseState();

        GetMousePosition();
    }
    private void GetMousePosition()
    {
        Event e = Event.current;
        if (e != null)
        {
            if(e.type == EventType.MouseMove)
            {
                MousePosition = e.mousePosition;
            }
            

        }
    }
    private void OnPauseState()
    {
        Event e = Event.current;

        if (e.type == EventType.ValidateCommand && e.commandName == "Paste")
        {
            PauseStateAction();
            e.Use();
        }

    }

    private void OnCopyState()
    {
        Event e = Event.current;

        if (e.type == EventType.ValidateCommand && e.commandName == "Copy")
        {
            CopyStateAction(SelectObjectController<S, T>.SelectObject);
            e.Use();
        }

    }

    private void MouseSelectObject()
    {
        Event e = Event.current;
        if (e.button == 0 && e.type == EventType.MouseDown)
        {
            if (SM_DrawBGGUIUtils.controlWindowRange.Contains(e.mousePosition))
            {
                object selectItem = null;
                if (CheckSelectStateGUI(e.mousePosition, out selectItem))
                {

                    SelectObjectController<S, T>.SelectItemObject(selectItem);
                }
                else if (CheckSelectTransitionGUI(e.mousePosition, out selectItem))
                {
                    SelectObjectController<S, T>.SelectItemObject(selectItem);

                }
                //if (selectItem == null)
                //{
                //    SelectObjectController<S, T>.SelectObjectCancel();
                //}
                e.Use();
            }
        }
    }
    private bool CheckSelectStateGUI(Vector2 mousePosition, out object selectItem)
    {
        bool isSelect = false;
        selectItem = null;
        foreach (var item in SM_EditorController<S, T>.Instance.machineEditorData.stateDataList)
        {
            if (StateMachineUtils.MachineGridRectContainsMousePos(mousePosition, item.GUIRect))
            {

                isSelect = true;
                selectItem = item;
                break;
            }
        }

        return isSelect;
    }

    private bool CheckSelectTransitionGUI(Vector2 mousePosition, out object selectItem)
    {
        Vector2 v2 = StateMachineUtils.MousePos2MachineGridPos(mousePosition);
        selectItem = null;

        float lenth = float.PositiveInfinity;
        bool isSelect = false;

        foreach (var item in SM_EditorController<S, T>.Instance.machineEditorData.transitionDataGroupList)
        {

            if (item != null)
            {
                for (int i = 0; i < item.Length; i++)
                {
                    TransitionGUIData<T> arr = item[i];
                    if (arr == null)
                        continue;

                    float temoLenth;
                    Vector2[] LineSelfOneTrianglePoints = DrawTransitionGUIUtils<S, T>.GetTransitionSelfOneTrianglePoints(arr);
                    if (arr.IsLineSelf)
                    {
                        temoLenth = Vector2.Distance(LineSelfOneTrianglePoints[3], v2);
                    }
                    else
                    {
                        Vector2[] fromPoss = DrawTransitionGUIUtils<S, T>.GetFromTransitionPosition(arr);
                        Vector2[] toPoss = DrawTransitionGUIUtils<S, T>.GetToTransitionPosition(arr);
                        temoLenth = HandleUtility.DistancePointLine(v2, fromPoss[i], toPoss[i]);
                    }

                    if (temoLenth < lenth && temoLenth < 10)
                    {
                        selectItem = arr;
                        isSelect = true;
                        break;
                    }
                }
            }

            if (isSelect) break;
        }

        return isSelect;
    }

    private void KeyboardDeleteItem()
    {
        Event e = Event.current;
        if (e.keyCode == KeyCode.Delete && e.type == EventType.KeyDown)
        {
            SelectObjectController<S, T>.DeleteSelectObjet();
            e.Use();
        }
    }

    private object dragObject = null;
    private void OnDragStateGUI()
    {
        Event e = Event.current;

        if (e.button == 0)
        {
            if (e.type == EventType.MouseDrag)
            {
                if (SelectObjectController<S, T>.SelectObject != null && SelectObjectController<S, T>.SelectObject is StateGUIData<S>)
                {
                    if (dragObject != null)
                    {
                        StateGUIData<S> s = (StateGUIData<S>)SelectObjectController<S, T>.SelectObject;
                        Vector2 pos = StateMachineUtils.MousePos2MachineGridPos(e.mousePosition);
                        pos = pos - SM_EditorConstValue.State_GUI_Size / 2f;

                        s.stateData.editorPosition = pos;
                        e.Use();
                    }

                    object temp = null;
                    if (dragObject == null && CheckSelectStateGUI(e.mousePosition, out temp) && SM_DrawBGGUIUtils.controlWindowRange.Contains(e.mousePosition))
                    {
                        if (SelectObjectController<S, T>.SelectObject != null && SelectObjectController<S, T>.SelectObject == temp)
                        {
                            dragObject = temp;
                            e.Use();
                        }
                    }
                }
            }
            if (dragObject != null && e.type == EventType.MouseUp)
            {
                dragObject = null;
                e.Use();
            }
        }
    }

    /// <summary>
    /// 鼠标右键空白区域
    /// </summary>
    public void MouseBGEmptyRightClikEvent()
    {
        Event e = Event.current;

        if (e.button == 1 && e.type == EventType.ContextClick)
        {
            if (SM_DrawBGGUIUtils.controlWindowRange.Contains(e.mousePosition))
            {
                object selectItem = null;
                if (!CheckSelectStateGUI(e.mousePosition, out selectItem) && !CheckSelectTransitionGUI(e.mousePosition, out selectItem))
                {
                    GenericMenu menu = new GenericMenu();
                    menu.AddItem(new GUIContent("New State"), false, AddNewMachineStateGUIOnMouseMenu, e.mousePosition);
                    if (SelectObjectController<S, T>.CopyStateData != null)
                    {
                        menu.AddItem(new GUIContent("Pause"), false, PauseStateAction);
                    }
                    else
                    {
                        menu.AddDisabledItem(new GUIContent("Pause"));
                    }
                    menu.AddSeparator("");
                    menu.ShowAsContext();
                    e.Use();
                }

            }
        }
    }
    private void AddNewMachineStateGUIOnMouseMenu(object mousePos)
    {
        Vector2 mPos = (Vector2)mousePos;
        mPos = StateMachineUtils.MousePos2MachineGridPos(mPos);
        SM_EditorController<S, T>.Instance.machineData.AddState( mPos, "New State");

        //Debug.Log("AddNewMachineStateGUIOnMouseMenu :" + mPos);
    }
    private bool isRunNewTran = false;
    private void NewTransitionStart(object obj)
    {
        DrawTransitionGUIUtils<S, T>.isCreateNewTranstion = true;
        DrawTransitionGUIUtils<S, T>.startPositionMs = (StateGUIData<S>)obj;
        //Debug.Log("NewTransitionStart");
        isRunNewTran = true;
    }

    public void OnMachineStateMouseRightClickMenu()
    {
        if (DrawTransitionGUIUtils<S, T>.isCreateNewTranstion)
            return;
        Event e = Event.current;
        if (e.button == 1 && e.type == EventType.ContextClick)
        {
            object selectItem = null;
            if (CheckSelectStateGUI(e.mousePosition, out selectItem))
            {
                if (!SelectObjectController<S, T>.IsSelectThis(selectItem))
                {
                    SelectObjectController<S, T>.SelectItemObject(selectItem);
                }
                else
                {
                    GenericMenu menu = new GenericMenu();
                    menu.AddItem(new GUIContent("New Transition"), false, NewTransitionStart, selectItem);
                    menu.AddItem(new GUIContent("Copy"), false, CopyStateAction, selectItem);
                    if(SelectObjectController<S, T>.CopyStateData != null)
                    {
                        menu.AddItem(new GUIContent("Pause"), false, PauseStateAction);
                    }
                    else
                    {
                        menu.AddDisabledItem(new GUIContent("Pause"));
                    }
                    menu.AddSeparator("");
                    menu.AddItem(new GUIContent("Delete"), false, SelectObjectController<S, T>.DeleteSelectObjet);
                   
                    menu.ShowAsContext();
                }
                e.Use();

            }

        }
    }

    private void PauseStateAction()
    {
        if (SelectObjectController<S, T>.CopyStateData == null)
            return;

        string json = JsonUtils.ToJson(SelectObjectController<S, T>.CopyStateData);
        S s = JsonUtils.FromJson<S>(json);
        Vector2 mPos = StateMachineUtils.MousePos2MachineGridPos(MousePosition);
        s.editorPosition = mPos - SM_EditorConstValue.State_GUI_Size/2;
        s.transitionFromStateIDs.Clear();
        s.transitionToStateIDs.Clear();
        win.machineData.AddState(s);
    }

    private void CopyStateAction(object obj)
    {
        StateGUIData<S> sGUI = (StateGUIData<S>)obj;
        if (sGUI == null)
            return;
        SelectObjectController<S, T>.CopyStateData = sGUI.stateData;
        win.win.ShowNotification(new GUIContent( "已复制"));
    }

    private void OnEndNewTransitionEvent()
    {
        if (DrawTransitionGUIUtils<S, T>.isCreateNewTranstion)
        {
            Event e = Event.current;
            if (e.type == EventType.MouseMove)
            {
                DrawTransitionGUIUtils<S, T>.toPosition = StateMachineUtils.MousePos2MachineGridPos(e.mousePosition);
                e.Use();
            }
            if (e.isMouse)
            {
                if (e.button == 0)
                {
                    if (isRunNewTran)
                    {
                        isRunNewTran = false;
                        e.Use();
                        return;
                    }
                    object selectItem = null;
                    if (CheckSelectStateGUI(e.mousePosition, out selectItem))
                    {
                        Debug.Log("AddTransition");
                        SM_EditorController<S, T>.Instance.machineData.AddTransition(DrawTransitionGUIUtils<S, T>.startPositionMs.stateData.id, ((StateGUIData<S>)selectItem).stateData.id);
                        DrawTransitionGUIUtils<S, T>.isCreateNewTranstion = false;
                        e.Use();
                    }

                }
                else if (e.button == 1)
                {
                    DrawTransitionGUIUtils<S, T>.isCreateNewTranstion = false;
                    e.Use();
                }
            }

        }
    }
}